#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;

int add(int x, int y)
{
    cout << "int add(int, int)" << endl;
    return x + y;
}

int func(int x, int y, int z)
{
    cout << "int func(int, int, int)" << endl;
    return x * y * z;
}

class Example
{
public:
    /* static int add(int x, int y) */
    //隐含的this指针
    int add(int x, int y)
    {
        cout << "int Example::add(int, int)" << endl;
        return x + y;
    }
};

void test()
{
    //C中的函数，函数名就是函数的入口地址
    //函数的形态（类型）:函数的返回类型 + 参数列表
    //函数的参数列表：参数的个数、参数的顺序、参数的类型
    //int(int, int)--->int()
    /* auto f = bind(add, 1, 3); */
    auto f = bind(&add, 1, 3);
    cout << "f() = " << f() << endl;

    cout << endl;
    auto f2 = bind(func, 10, 20, 30);
    cout << "f2() = " << f2() << endl;

    cout << endl;
    Example ex;
    auto f3 = bind(&Example::add, &ex, 30, 70);
    cout <<"f3() = " << f3() << endl;

    cout << endl;
    //占位符
    auto f4 = bind(add, 1, std::placeholders::_1);
    cout << "f4(9) = " << f4(9) << endl;
}

void func2(int x1, int x2, int x3, const int &x4, int x5)
{
    cout << "x1 = " << x1 << endl
         << "x2 = " << x2 << endl
         << "x3 = " << x3 << endl
         << "x4 = " << x4 << endl
         << "x5 = " << x5 << endl;
}

void test2()
{
    using namespace std::placeholders;
    //占位符本身代表的是函数的形参的位置
    //占位符中的数字代表的是函数的实参的位置
    //bind进行传参的时候，使用的是值传递
    //std::cref,引用的包装器 const reference
    //std::ref,引用的包装器 reference
    int number = 100;
    auto f = bind(func2, 10, _3, _1, std::cref(number), number);
    number = 500;
    f(40, 50, 60, 70, 80);//多余的参数直接扔掉
}

int main(int argc, char *argv[])
{
    test2();
    return 0;
}

